﻿//17.2023 - 08 - 09 - 集训营 - 指针(2)
//第11讲：深入理解指针(1)

//1. 2023-11-12 16:38:19 Sunday (unfinished)

/*
#include <stdio.h>

int main()
{
	//int num = 10;
	//int* p = &num;

	//char ch = 'w';
	//char* pc = &ch;

	//printf("%zd\n", sizeof(p));//
	//printf("%zd\n", sizeof(pc));//

	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(long*));
	printf("%zd\n", sizeof(float*));
	printf("%zd\n", sizeof(double*));

	return 0;
}
*/

//2. 2023-11-19 16:47:44 Sunday 7 day interval

#include <stdio.h>

//int main()
//{
//	int num = 10;
//	int* pi = &num;
//
//	char ch = 'w';
//	char* pc = &ch;
//
//	printf("%zd\n", sizeof(pi));
//	printf("%zd\n", sizeof(pc));
//
//
//	return 0;
//}

//3.2023-11-22 13:38:17 星期三
//int main()
//{
//	int n = 0x11223344;
//	int* p = &n;
//	*p = 0;
//	printf("%d\n", n);
//
//	return 0;
//}

//4.2023-11-23 13:37:37 星期四
//int main()
//{
//	int n = 0x11223344;
//	char* p = (char*)&n;
//	*p = 0;
//	printf("%d\n", n);
//
//	return 0;
//}

//5. 2023-11-24 13:36:12 Fiday.

//int main()
//{
//	int a = 0x11223344;
//	int* pi = &a;
//	char* pc = &a;
//
//	printf("pi     = %p\n", pi);
//	printf("pi + 1 = %p\n", pi + 1);
//	printf("pc     = %p\n", pc);
//	printf("pc + 1 = %p\n", pc + 1);
//
//	return 0;
//}

//6. 2023-11-27 13:28:49 Monday
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	//            0  1  2...
//	//下标的方式
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	printf("\n");
//
//	return 0;
//}

//7. 2023-11-28 13:29:03 Tuesday
//int main()
//{
//	int m = 100;
//	const int n = 10;
//	int       *       p = &n;
//
//
//
//
//	return 0;
//}

//8. 2023-11-29 13:27:32 wednesday
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	//使用指针
//	int* p = &arr[0];
//
//	return 0;
//}

//9. 2023-11-30 13:37:49 Thursday
//int main()
//{
//	int arr[10] = { 0 };
//	int ret = &arr[9] - &arr[0];
//
//	printf("%d\n", ret);
//
//	return 0;
//}
 
//10. 2023-12-1 13:41:34 Friday
//int main()
//{
//	char ch[7] = { 0 };
//	int arr[10] = { 0 };
//
//	int ret = &arr[9] - &ch[5];
//	int ret2 = &arr[9] - &arr[0];
//
//	int ret3 = &arr[0] + 9;//&arr[9];
//	printf("%d\n", ret3);
//
//	return 0;
//}

//11. 2023-12-2 13:36:39 Saturday
//#include <string.h>
////strlen - string length
////功能：求字符串长度
//
//
//int main()
//{/*
//	char ch[] = "abcedf";
//	int len = strlen(ch);
//	printf("%d\n", len);*/
//
//	printf("%d\n", strlen("abcdef"));
//
//	return 0;
//}

//12. 2023-12-3 10:47:58 Sunday

//int My_strlen(char* str)
//{
//	int count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}

//int My_strlen(char* str)
//{
//	char* start = str;
//	while (*str != '\0')
//	{
//		str++;
//	}
//	return str - start;
//}
//
//int main()
//{
//	char ch[] = "abcdef";
//	int len = My_strlen(ch);
//
//	printf("len = %d\n", len);
//
//	return 0;
//}

//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	return 0;
//}

//int* test()
//{
//	int n = 10;
//	return &n;
//}
//
//int main()
//{
//	int* p = test();
//
//	return 0;
//}
//
//




















//2023-12-11 Monday 13:28:34 
//5. 指针运算
//5.1 指针+-整数
//来自课件 - 预习
//通过指针遍历数组
#include <stdio.h>

//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int* p = arr;
//	int i = 0;
//
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));//p + i 这里就是指针+整数；让地址每次+i，再解引用
//	}
//	printf("\n");
//
//	return 0;
//}


//来自课上 - 预习；不过这是我凭自己的理解写的，和课上的一样
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int* p = arr;
//	int i = 0;
//
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *p);//先解引用找到p指向的元素
//		p++;//再让每次的地址p+1...
//	}
//	printf("\n");
//
//	return 0;
//}


//2023-12-17 Sunday 15:45:18 
//来自课上 - 已练习
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	//使用指针
//	int* p = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *p);
//		p++;//p = p+1
//
//	}
//
//	/*for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));
//	}*/
//	//
//	//p+i ---> &arr[i]
//	//
//	return 0;
//}


//5.2 指针-指针
//来自课件 - 预习
//模拟实现strlen函数
//int my_strlen(char* pc)
//{
//	char* start = pc;//初始地址
//
//	while (*pc != '\0')
//	{
//		pc++;
//	}
//
//	return pc - start;//最终地址 - 初始地址
//}
//
//int main()
//{
//	printf("len = %d\n", my_strlen("abc"));
//
//	return 0;
//}


//2023-12-19 Tursday 13:35:52
//另一种方式
//int my_strlen(char* pc)
//{
//	int count = 0;//计数
//
//	while (*pc != '\0')
//	{
//		count++;
//		pc++;
//	}
//
//	return count;
//}
//
//int main()
//{
//	printf("len = %d\n", my_strlen("abc"));
//
//	return 0;
//}


//5.3 指针的关系运算
//来自课件 - 预习 - 还需代入测试 （p < p + sz）
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int* p = &arr[0];
//
//
//	while (p < arr + sz)//指针的大小比较 （p < p + sz）error
//	{
//		printf("%d ", *p);
//		p++;
//	}
//
//	return 0;
//}
//
//
//






























//2023-12-25 13:32:05 Monday
//7. assert断⾔
//#define NDEBUG//定义宏，是assert的开关
//#include <assert.h>
//
//int main()
//{
//	int *p = 0x11223344;
//
//	assert(p != 0x11223344);
//
//	printf("%d\n", p);
//
//	return 0;
//}


//2023-12-26 Tuesday 13:34:56
//8. 指针的使⽤和传址调⽤
//8.1 传址调⽤
//写⼀个函数，交换两个整型变量的值
//void Swap1(int x, int y)
//{
//	int tmp = x;
//	x = y;
//	y = tmp;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//
//	printf("交换前a和b的值：%d %d\n", a, b);
//
//	Swap1(a, b);
//
//	printf("交换后a和b的值：%d %d\n", a, b);
//
//	return 0;
//}


//2023-12-30 Satuarday 11:37:10 
//利用指针的方式
//void Swap2(int* px, int* py)
//{
//  别忘记解引用，temp是int，不是int*
//	int tmp = *px;
//	*px = *py;
//	*py = tmp;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//	
//	printf("交换前的值：%d %d\n", a, b);
//
//	Swap2(&a, &b);
//
//	printf("交换后的值：%d %d\n", a, b);
//
//	return 0;
//}


//8.2 strlen的模拟实现
//含多种方式，考虑用哪种效率高？
//计数器方式
//#define NDEBUG
//#include <assert.h>
//#include <stdio.h>
//
//int my_strlen(const char* str)//const确保*str不被改，但是为什么要这样做呢？
//{
//	int count = 0;
//	assert(str);//确保str的有效性，避免为空指针
//
//	while (*str != '\0')//利用指针的加法运算，让字符串的第一个地址逐渐递增
//	{
//		count++;
//		str++;
//	}
//
//	return count;
//}
//
//int main()
//{
//	printf("len = %d\n", my_strlen("abcdef"));
//
//	return 0;
//}



















//2023-12-30 Saturday 19:20:34
//5. 指针运算
//5.2 指针 - 指针 （没搞明白为什么是这个结果）
//计算字符串的长度
//来自课件
//int my_strlen(char* s)
//{
//	char* start = s;//初地址
//
//	while (*s != '\0')
//	{
//		s++;
//	}
//
//	return s - start;//末地址 - 初地址 = 元素个数 ？
//}
//
//int main()
//{
//	printf("len = %d\n", my_strlen("abc"));
//
//	return 0;
//}


//来自课上
//指针-指针(地址-地址)的前提是两个指针指向同一块空间的
//得到的值的绝对值，是指针和指针之间元素的个数
////int* p + 1 ---> 4//跳过4个字节
//int main()
//{
//	char ch[7] = { 0 };
//	int arr[10] = { 0 };
//
//	&arr[9] - &ch[5];//error, 指针-指针(地址-地址)的前提是两个指针指向同一块空间的
//	int ret = &arr[9] - &arr[0];//指针 - 指针（地址 - 地址）
//
//	//&arr[0] + 9 ---> &arr[9] ？ 我的理解：理解不了，不用管，直接看成 0 + 9
//
//	printf("%d\n", ret);//9
//
//	return 0;
//}


//2023-12-31 Sunday 08:42:03
//strlen函数
//strlen - string length 
//功能：求字符串长度
#include <stdio.h>
//#include <string.h>
//int main()
//{
//	char ch[] = "abc";
//	int ret = strlen(ch);
//
//	printf("len = %d\n", ret);
//
//	return 0;
//}


//模拟实现strlen函数
//利用计算器的方式
//int my_strlen(char* str)
//{
//	int count = 0;
//
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//
//	return count;
//}
//
//int main()
//{
//	char ch[] = "abc";
//	int len = my_strlen(ch);
//
//	printf("len = %d\n", len);
//
//	return 0;
//}


//利用指针 - 指针的方式
//int my_strlen(char* str)
//{
//	char* start = str;
//
//	while (*str != '\0')
//	{
//		str++;
//	}
//
//	return str - start;
//}
//
//int main()
//{
//	char ch[] = "abc";
//	int len = my_strlen(ch);
//
//	printf("len = %d\n", len);
//
//	return 0;
//}


//利用指针的关系运算打印数组
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	//int*p = &arr[0];
//	int* p = arr;//数组名就是数组首元素的地址
//
//	int i = 0;
//	for (i = 0; i < sz; i++)//指针的关系运算
//	{
//		//printf("%d ", *(p++));
//
//		printf("%d ", *p);
//		p++;
//	}
//
//	return 0;
//}


//指针变量未初始化
//int main()
//{
///*	int n = 10;
//	int* p;
//	p = &n;*/ //Correctness
//
//	//int* p;//野指针, 局部变量，如果不初始化的话，会得到一个随机值
//	//*p = 20;//你怎么可能随便丢个20元给别人呢
//
//	//int n = 10;
//	//int nnn = 30;
//	//int* p = &n; //Correctness
//	//*p = 20;
//	//p = &nnn;
//
//
//	return 0;
//}


//避免数组越界访问
//int main()
//{
//	int arr[10] = { 0 };
//
//	int* p = arr;
//
//	int i = 0;
//	for (i = 0; i <= 11; i++)//i < 12
//	{
//		*(p++) = i;//依次逐加赋值给数组，然后地址往后走
//		/**p = i;
//		p++;*/
//		//他们的两种写法是一样的
//	}
//
//	return 0;
//}


//避免返回局部变量的地址
int test()
{
	int n = 100;

	return &n;//返回空间已释放
}

int main()
{
	int* p = test();//地址是存进去了，但你不能去找到他，就像我给你地址，但我退房了，你还去那个房间，这就是非法访问了
	*p = 0;
	printf("%d\n", *p);//编译是过去了，但会报警告，那个值也确实被改为了0

	return 0;
}













